package com.gitee.wsl.unit.angle.ext

import com.gitee.wsl.ext.bitcode.umod
import com.gitee.wsl.math.Math
import com.gitee.wsl.math.getSliceAngle
import com.gitee.wsl.mathematics.vector.vec2.Vector2
import com.gitee.wsl.unit.angle.AngleUnit
import com.gitee.wsl.unit.angle.toRadians


//fun cos(angle: AngleUnit): Double = angle.cos()

//fun sin(angle: AngleUnit): Double = angle.sin()

//计算
fun AngleUnit.tan() = kotlin.math.tan(radian)
fun AngleUnit.tanF() = kotlin.math.tan(radian).toFloat()

fun AngleUnit.sin() = kotlin.math.sin(radian)
fun AngleUnit.sinF() = kotlin.math.sin(radian).toFloat()

fun AngleUnit.cos() = kotlin.math.cos(radian)
fun AngleUnit.cosF() = kotlin.math.cos(radian).toFloat()

infix fun AngleUnit.umod(angle: AngleUnit):AngleUnit = AngleUnit.Radians(radian umod angle.radian)

/**
 * Obtains the average of two angles. This method is commutative, so `midAngle(m, n)` and
 * `midAngle(n, m)` are equivalent.
 *
 * @param a1 the first angle.
 * @param a2 the second angle.
 *
 * @return the average of `a1` and `a2`
 */
fun AngleUnit.Companion.average(a1: AngleUnit, a2: AngleUnit) = fromDegrees(0.5 * (a1.degrees + a2.degrees))

fun AngleUnit.Companion.max(a: AngleUnit, b: AngleUnit) = if (a.degrees >= b.degrees) a else b

fun AngleUnit.Companion.min(a: AngleUnit, b: AngleUnit) = if (a.degrees <= b.degrees) a else b

fun AngleUnit.Companion.atan(value:Float) = AngleUnit.Radians(kotlin.math.atan(value))
fun AngleUnit.Companion.atan(value:Double) = AngleUnit.Radians(kotlin.math.atan(value))

fun AngleUnit.Companion.asin(v: Double): AngleUnit = kotlin.math.asin(v).toRadians()
fun AngleUnit.Companion.asin(v: Float): AngleUnit = kotlin.math.asin(v).toRadians()

fun AngleUnit.Companion.acos(v: Double): AngleUnit = kotlin.math.acos(v).toRadians()
fun AngleUnit.Companion.acos(v: Float): AngleUnit = kotlin.math.acos(v).toRadians()

fun AngleUnit.Companion.arcCosine(v: Double): AngleUnit = kotlin.math.acos(v).toRadians()
fun AngleUnit.Companion.arcCosine(v: Float): AngleUnit = kotlin.math.acos(v).toRadians()

fun AngleUnit.Companion.arcSine(v: Double): AngleUnit = kotlin.math.asin(v).toRadians()
fun AngleUnit.Companion.arcSine(v: Float): AngleUnit = kotlin.math.asin(v).toRadians()

fun AngleUnit.Companion.arcTangent(x: Double, y: Double): AngleUnit = kotlin.math.atan2(x, y).toRadians()
fun AngleUnit.Companion.arcTangent(x: Float, y: Float): AngleUnit = kotlin.math.atan2(x, y).toRadians()
fun AngleUnit.Companion.arcTangent(v: Vector2<*, *>): AngleUnit = kotlin.math.atan2(v.x.toDouble(), v.y.toDouble()).toRadians()

/**
 * Sign of direction change needed to travel from one angle to another.
 *
 *
 * For angles that are 180 degrees apart from each other, both directions have the same travel
 * distance, so either direction is shortest. The value 1.0 is returned in this case.
 *
 * @param from The angle travel starts from, in degrees.
 * @param to The angle travel ends at, in degrees.
 * @return -1 if decreasing from leads to the shortest travel distance, 1 if increasing from leads
 * to the shortest travel distance.
 */
fun AngleUnit.rotationDirection(to: AngleUnit): Double {
    val increasingDifference = (to - this).sanitize360()
    return if (increasingDifference <= AngleUnit.PI) 1.0 else -1.0
}

/**
 * 将百分比转换为图心角角度
 * @param totalAngle    总角度(如:360度)
 * @param percentage    百分比
 * @return 圆心角度
 */
fun AngleUnit.getSliceRadianAngle(percentage: Float) =
    AngleUnit.Radians(Math.getSliceAngle(radian.toFloat(), percentage))

